import React, { useEffect, useRef, useState } from 'react'
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { DragControls } from 'three/examples/jsm/controls/DragControls'
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'

interface ObjectData {
  name: string
  quantity: number
  stock: number
}

export default function ObjectLabels() {
  const canvasRef = useRef<HTMLCanvasElement>(null)
  const labelContainerRef = useRef<HTMLDivElement>(null)
  const [objectsData, setObjectsData] = useState<ObjectData[]>([])

  useEffect(() => {
    if (!canvasRef.current || !labelContainerRef.current) return

    const scene = new THREE.Scene()
    const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
    const renderer = new THREE.WebGLRenderer({ canvas: canvasRef.current, antialias: true })
    const labelRenderer = new CSS2DRenderer()

    renderer.setSize(window.innerWidth, window.innerHeight)
    renderer.setClearColor(0x5d544a)

    labelRenderer.setSize(window.innerWidth, window.innerHeight)
    labelRenderer.domElement.style.position = 'absolute'
    labelRenderer.domElement.style.top = '0'
    labelRenderer.domElement.style.pointerEvents = 'none'
    labelContainerRef.current.appendChild(labelRenderer.domElement)

    camera.position.set(5, 6, 5)

    const controls = new OrbitControls(camera, renderer.domElement)

    // Add ambient light
    const ambientLight = new THREE.AmbientLight(0xffffff, 1)
    scene.add(ambientLight)

    // Add axes helper
    const axesHelper = new THREE.AxesHelper(20)
    scene.add(axesHelper)

    // Function to create label
    const createLabel = (object: THREE.Object3D, data: ObjectData) => {
      const labelDiv = document.createElement('div')
      labelDiv.className = 'label'
      labelDiv.innerHTML = `
        <div class="label-content">
          <h3>${data.name}</h3>
          <p>Quantity: ${data.quantity}</p>
          <p>Stock: ${data.stock}</p>
        </div>
      `
      const label = new CSS2DObject(labelDiv)
      label.position.set(0, object.geometry.boundingBox.max.y + 0.5, 0)
      object.add(label)

      // Create guide line
      const lineGeometry = new THREE.BufferGeometry().setFromPoints([
        new THREE.Vector3(0, 0, 0),
        new THREE.Vector3(0, object.geometry.boundingBox.max.y + 0.5, 0)
      ])
      const lineMaterial = new THREE.LineBasicMaterial({ color: 0xffffff })
      const guideLine = new THREE.Line(lineGeometry, lineMaterial)
      object.add(guideLine)
    }

    // Add triangle (CircleGeometry)
    const triangleGeometry = new THREE.CircleGeometry(1, 3)
    triangleGeometry.computeBoundingBox()
    const triangleMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 })
    const triangle = new THREE.Mesh(triangleGeometry, triangleMaterial)
    triangle.position.set(7, 3, -2)
    triangle.userData = { name: 'Yellow Triangle', type: 'CircleGeometry' }
    scene.add(triangle)
    createLabel(triangle, { name: 'Yellow Triangle', quantity: 1, stock: 10 })

    // Add textured cubes
    const textureLoader = new THREE.TextureLoader()
    const texture = textureLoader.load('/placeholder.svg?height=256&width=256')

    const cubeGeometry = new THREE.BoxGeometry(3, 3, 3)
    cubeGeometry.computeBoundingBox()
    const cubeMaterial = new THREE.MeshBasicMaterial({ map: texture })

    const cube1 = new THREE.Mesh(cubeGeometry, cubeMaterial)
    cube1.position.set(0, 0, 0)
    cube1.userData = { name: 'Textured Cube 1', type: 'TexturedCube' }
    scene.add(cube1)
    createLabel(cube1, { name: 'Textured Cube 1', quantity: 5, stock: 20 })

    const cube2 = new THREE.Mesh(cubeGeometry, cubeMaterial)
    cube2.position.set(-4, 0, 0)
    cube2.userData = { name: 'Textured Cube 2', type: 'TexturedCube' }
    scene.add(cube2)
    createLabel(cube2, { name: 'Textured Cube 2', quantity: 3, stock: 15 })

    // Load GLB model
    const loader = new GLTFLoader()
    loader.load('/assets/3d/duck.glb', (gltf) => {
      gltf.scene.position.set(4, 0, 0)
      gltf.scene.scale.set(0.5, 0.5, 0.5)
      
      // Traverse the GLB model and set userData for each mesh
      gltf.scene.traverse((child) => {
        if (child.isMesh) {
          child.userData = { name: 'Duck GLB Model', type: 'GLBModel' }
          child.geometry.computeBoundingBox()
          createLabel(child, { name: 'Duck GLB Model', quantity: 1, stock: 5 })
        }
      })
      
      scene.add(gltf.scene)

      // Set up drag controls
      const objects = scene.children.filter((child) => child.isMesh || child.isGroup)
      const dragControls = new DragControls(objects, camera, renderer.domElement)

      dragControls.addEventListener('dragstart', () => {
        controls.enabled = false
      })

      dragControls.addEventListener('dragend', () => {
        controls.enabled = true
      })
    })

    // Handle window resize
    const handleResize = () => {
      camera.aspect = window.innerWidth / window.innerHeight
      camera.updateProjectionMatrix()
      renderer.setSize(window.innerWidth, window.innerHeight)
      labelRenderer.setSize(window.innerWidth, window.innerHeight)
    }
    window.addEventListener('resize', handleResize)

    // Animation loop
    const animate = () => {
      requestAnimationFrame(animate)
      controls.update()
      renderer.render(scene, camera)
      labelRenderer.render(scene, camera)
    }
    animate()

    // Cleanup
    return () => {
      window.removeEventListener('resize', handleResize)
      renderer.dispose()
      labelRenderer.dispose()
    }
  }, [])

  return (
    <div className="relative w-full h-screen">
      <canvas ref={canvasRef} className="w-full h-full" />
      <div ref={labelContainerRef} className="absolute top-0 left-0 w-full h-full pointer-events-none" />
    </div>
  )
}

